#include "app_i2c_bus.h"

#define SDA_H  thiss->sda_out->set(thiss->sda_out)
#define I2C_delay i2c_delay                                // Quick delay
#define SCL_H  thiss->scl->set(thiss->scl)               // SCL = 1 
#define SDA_L  thiss->sda_out->clr(thiss->sda_out)                                   // SDA = 0
#define SCL_L  thiss->scl->clr(thiss->scl)                                    // SCL = 0
#define SDA_inputmode thiss->sda_out->setdir(thiss->sda_out,GPIO_MODE_INPUT,GPIO_PULL_UP)
#define SDA_outputmode thiss->sda_out->setdir(thiss->sda_out,GPIO_MODE_OUTPUT,GPIO_PULL_UP)
#define SDA_read thiss->sda_out->get(thiss->sda_out)
#define BIT7  0x80
void i2c_delay(void)
{
    u8 i = 100; 
    while(i)
    {
        i--;
    }
}
uint8_t i2c_start(struct I2C_BUS *thiss)
{
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
//    if(!SDA_read)return FALSE;	
    SDA_L;
    I2C_delay();
//    if(SDA_read) return FALSE;	
    SCL_L;
    I2C_delay();
    return TRUE;
}

void i2c_stop(struct I2C_BUS *thiss)
{
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SDA_H;
    I2C_delay();
}
void I2C_Ack(struct I2C_BUS *thiss)
{
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();
}


void I2C_NoAck(struct I2C_BUS *thiss)
{
    SCL_L;
    I2C_delay();
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();
}
uint8_t I2C_WaitAck(struct I2C_BUS *thiss)	
{
    SCL_L;
    I2C_delay();
    SDA_H;
    I2C_delay();
    SCL_H;
    SDA_inputmode;
    I2C_delay();
    I2C_delay();
    if(SDA_read)
    {
        SCL_L;
        SDA_outputmode;
        return FALSE;
    }
    SCL_L;
    SDA_outputmode;
    return TRUE;
}
void  I2C_SendByte(struct I2C_BUS *thiss,u8 SendByte)
{
    u8 i = 8;
    while(i--)
    {
        SCL_L;
        I2C_delay();
        if(SendByte & 0x80)
            SDA_H;
        else
            SDA_L;
        SendByte <<= 1;
        I2C_delay();
        SCL_H;
        I2C_delay();
    }
    SCL_L;
}
u8 I2C_ReceiveByte(struct I2C_BUS *thiss)
{
    u8 i = 8;
    u8 ReceiveByte = 0;
    SDA_H;
    I2C_delay();
    SDA_inputmode;
    while(i--)
    {
        ReceiveByte <<= 1;
        SCL_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read)
        {
            ReceiveByte |= 0x01;
        }
    }
    SCL_L;
    SDA_outputmode;
    return ReceiveByte;
}

void i2c_bus_init(struct I2C_BUS *thiss,struct AT32F415GPIO *sda_out,struct AT32F415GPIO *sda_in,struct AT32F415GPIO *scl)
{
    gpio_init_pin(sda_out);
    gpio_init_pin(scl);
    thiss->sda_out = sda_out;
    thiss->sda_in = sda_in;
    thiss->scl = scl;
    thiss->start = i2c_start;
    thiss->stop = i2c_stop;
    thiss->txByte = I2C_SendByte;
    thiss->rxByte = I2C_ReceiveByte; 
    thiss->ack = I2C_Ack;
    thiss->noack = I2C_NoAck;
    thiss->waitack = I2C_WaitAck;
}
